//
//  HomeAutomationCondition.swift
//  home
//
//  Created by Yun Zeng on 2019/8/6.
//  Copyright © 2019 Yun Zeng. All rights reserved.
//

import Foundation

// 自动化执行条件之: 时间段
// 例如: 晚上9点-第二天早上8点
class ConditionPeriod: Codable {
    var after: Int
    var before: Int
    
    init(after: Int, before: Int) {
        self.after = after
        self.before = before
    }
}

// 自动化触发条件之: 家人位置状态
// 比如: 仅当云在家时执行
class ConditionLocation: Codable {
    enum ConditionType: Int {
        case allLeave = 0       // 所有人都离家
        case allArrive = 1      // 所有人在家
        case someoneArrive = 2  // 执行某几个人在家
    }
    
    var members: [String]
    var conditionType: Int
    
    private enum CodingKeys: String, CodingKey {
        case members
        case conditionType = "trigger_t"
    }
    
    init(members: [String], type: ConditionType) {
        self.members = members
        self.conditionType = type.rawValue
    }
}

// 自动化执行条件之: 服务属性
// 比如: 当我回家时，当卧室的温度大于28度，打开空调
// 卧室温度大于28度 属于 自动化执行条件的服务属性条件
class ConditionCharacteristic: Codable {
    enum ThresholdType: Int {
        case equal = 0
        case greater = 1
        case smaller = 2
    }
    
    var aid: String
    var sid: Int
    var cid: Int
    var value: AnyJSONType
    var thresholdType: Int = ThresholdType.equal.rawValue
    
    private enum CodingKeys: String, CodingKey {
        case aid
        case sid
        case cid
        case value
        case thresholdType = "threshold_t"
    }
    
    init?(characteristic: HMCharacteristic, target: AnyJSONType, type: ThresholdType = .equal) {
        guard let accessory = characteristic.service?.accessory else {
            return nil
        }
        guard let service = characteristic.service else {
            return nil
        }
        self.aid = accessory.id
        self.sid = service.id
        self.cid = characteristic.id
        self.value = target
        self.thresholdType = type.rawValue
    }
}

// 自动化执行条件
class AutomationCondition: Codable {
    enum ConditionType {
        case period(ConditionPeriod)
        case location(ConditionLocation)
        case characteristic(ConditionCharacteristic)
        case unknown
    }
    
    var type: String
    var condition: ConditionType
    private enum CodingKeys: String, CodingKey {
        case type
        case condition = "desc"
    }
    
    init(type: String, condition: ConditionType) {
        self.type = type
        self.condition = condition
    }
}

// 自动化执行条件解析
extension AutomationCondition.ConditionType: Codable {
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let period = try? container.decode(ConditionPeriod.self) {
            self = .period(period)
        } else if let location = try? container.decode(ConditionLocation.self) {
            self = .location(location)
        } else if let characteristic = try? container.decode(ConditionCharacteristic.self) {
            self = .characteristic(characteristic)
        } else {
            self = .unknown
        }
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case let .period(period):
            try container.encode(period)
        case let .location(location):
            try container.encode(location)
        case let .characteristic(characteristic):
            try container.encode(characteristic)
        case .unknown:
            try container.encodeNil()
        }
    }
}
